package com.guigu.gulicommon.tools;

import com.guigu.gulicommon.exception.RequestException;
import lombok.extern.log4j.Log4j2;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static com.guigu.gulicommon.constant.enumes.res.ServerResCode.SEND_HTTP_REQUEST_FAILED;

/**
 * Http请求工具类
 *
 * @author 陈俊杰
 * @since 2024-8-3
 */
@Log4j2
public class HttpTool {

    private static final HttpClient httpClient;

    static {
        httpClient = HttpClientBuilder.create().build();
    }

    /**
     * 将响应体转换为字符串
     *
     * @param response 请求响应体
     * @return String 响应字符串
     */
    public static String getResponseBody(HttpResponse response) {
        try {
            if (response.getStatusLine().getStatusCode() != 200) {
                log.error("http响应码为:{}", response.getStatusLine().getStatusCode());
                throw new RequestException(SEND_HTTP_REQUEST_FAILED);
            }
            return EntityUtils.toString(response.getEntity(), ContentType.getOrDefault(response.getEntity()).getCharset());
        } catch (Exception e) {
            log.error("获取响应体失败,原因是:", e);
            throw new RequestException(SEND_HTTP_REQUEST_FAILED);
        }
    }


    /**
     * 在url上拼接路径参数和普通请求参数
     *
     * @param url        请求地址
     * @param params     请求参数
     * @param pathParams 路径参数
     */
    private static String appendUrl(String url, LinkedHashMap<String, String> params, LinkedHashMap<String, String> pathParams) {
        //1.设置路径参数
        if (pathParams != null && !pathParams.isEmpty()) {
            //1.1 检测url的最后一位是否为'/',如果有则不添加,没有就添加
            if (!url.endsWith("/")) {
                url = url + "/";
            }
            //1.2 拼接路径参数
            StringBuilder urlBuilder = new StringBuilder(url);
            //1.3LinkedHashMap转为列表
            List<Map.Entry<String, String>> pathParamsList = new ArrayList<>(pathParams.entrySet());
            for (int i = 0; i < pathParamsList.size(); i++) {
                if (!(i == pathParamsList.size() - 1)) {
                    //如果不是最后一个元素，则添加/
                    urlBuilder.append(pathParamsList.get(i).getValue()).append("/");
                } else {
                    //如果是最后一个元素，则不添加/
                    urlBuilder.append(pathParamsList.get(i).getValue());
                }
            }
            url = urlBuilder.toString();
        }


        //2.设置请求参数
        if (params != null && !params.isEmpty()) {
            //2.1 检测url里面是否有'?',有说明之前已经有参数了，没有则加上'?'
            if (!url.contains("?")) {
                url = url + "?";
            }
            //2.2 拼接请求参数
            StringBuilder urlBuilder = new StringBuilder(url);
            //LinkedHashMap转为列表
            List<Map.Entry<String, String>> paramsList = new ArrayList<>(params.entrySet());
            for (int i = 0; i < paramsList.size(); i++) {
                if (!(i == paramsList.size() - 1)) {
                    //如果不是最后一个元素，则添加&
                    urlBuilder.append(paramsList.get(i).getKey()).append("=").append(paramsList.get(i).getValue()).append("&");
                } else {
                    //如果是最后一个元素，则不添加&
                    urlBuilder.append(paramsList.get(i).getKey()).append("=").append(paramsList.get(i).getValue());
                }

            }
            url = urlBuilder.toString();
        }
        return url;
    }

    /**
     * 发送GET请求
     *
     * @param url        请求地址
     * @param params     请求参数
     * @param header     请求头
     * @param pathParams 请求路径参数
     * @return HttpResponse 响应体字符串
     */
    public static String sendGet(String url, LinkedHashMap<String, String> params, LinkedHashMap<String, String> header, LinkedHashMap<String, String> pathParams) {
        try {
            HttpGet httpGet = new HttpGet(appendUrl(url, params, pathParams));
            HttpResponse response = httpClient.execute(httpGet);
            return getResponseBody(response);
        } catch (Exception e) {
            log.error("发送GET请求失败,原因是:", e);
            return null;
        }
    }

    /**
     * 发送POST请求
     *
     * @param url        请求地址
     * @param params     请求参数
     * @param header     请求头
     * @param pathParams 路径参数
     * @return HttpResponse 响应体字符串
     */
    public static String sendPost(String url, LinkedHashMap<String, String> params, LinkedHashMap<String, String> header, LinkedHashMap<String, String> pathParams) {
        try {
            HttpPost httpPost = new HttpPost(appendUrl(url, params, null));
            HttpResponse response = httpClient.execute(httpPost);
            return getResponseBody(response);
        } catch (Exception e) {
            log.error("发送POST请求失败,原因是:", e);
            return null;
        }
    }
}
